
#include "IGlobal.h"
#include "member_BObject.h"

using namespace BWE;

member_BObject::member_BObject(BObject* object)
{
	boss = object;
	enabled = true;
	mutex_initialized = false;
}
member_BObject::~member_BObject()
{
	App_LockGlobalMutex();
	for (auto it = app_slotPackMap.begin(); it.valid(); ++it)
	{
		if (it.key() == boss)
		{
			app_slotPackMap.erase(it);
			it--;
			continue;
		}
		(*it).remove(boss);
	}
	App_UnlockGlobalMutex();
	SigSlotMap& gSigMap = this->globalSigSlotMap();
	for (auto it = gSigMap.begin(); it.valid(); ++it)
	{
		(*it).remove(boss);
	}
	StrSigSlotMap& gStrSigMap = this->globalStrSigSlotMap();
	for (auto it = gStrSigMap.begin(); it.valid(); ++it)
	{
		(*it).remove(boss);
	}
	if(mutex_initialized)
	{
#ifdef linux
		pthread_mutex_destroy(&mutex);
#else
		DeleteCriticalSection(&criticalSection);
#endif
	}
}

member_BObject::SigSlotMap& member_BObject::globalSigSlotMap()
{
	static SigSlotMap global_signal_slot_map;
	return global_signal_slot_map;
}
member_BObject::StrSigSlotMap& member_BObject::globalStrSigSlotMap()
{
	static StrSigSlotMap global_string_signal_slot_map;
	return global_string_signal_slot_map;
}

bool member_BObject::initMutex()
{
	if(!mutex_initialized)
	{
#ifdef linux
		int error = pthread_mutex_init(&mutex, 0);
		mutex_initialized = error == 0;
#endif
#ifdef _WIN32
		InitializeCriticalSection(&criticalSection);
		mutex_initialized = true;
#endif
	}
	return mutex_initialized;
}

void member_BObject::emit(int signal, const BValue& value)
{
	boss->emit(signal, value);
}
void member_BObject::emit(const BString& signal, const BValue& value)
{
	boss->emit(signal, value);
}
void member_BObject::post(BObject* receiver, int signal, const BValue& value)
{
	if (signal == 0)
		return;
	member_BObject::SlotArray& slots = sigSlotMap(signal);
	for (int i = 0; i < slots.size(); i++)
	{
		member_BObject::Slot& slot = slots[i];
		if (slot.object == receiver)
			slot(boss, value);
	}
	member_BObject::SigSlotMap& globalSigSlotMap = this->globalSigSlotMap();
	member_BObject::SlotArray& globalSlots = globalSigSlotMap(signal);
	for (int i = 0; i < globalSlots.size(); i++)
	{
		member_BObject::Slot& slot = globalSlots[i];
		if (slot.object == receiver)
			slot(boss, value);
	}
}
void member_BObject::post(BObject* receiver, const BString& signal, const BValue& value)
{
	if (signal.empty())
		return;
	member_BObject::SlotArray& slots = strSigSlotMap(signal);
	for (int i = 0; i < slots.size(); i++)
	{
		member_BObject::Slot& slot = slots[i];
		if (slot.object == receiver)
			slot(boss, value);
	}
	member_BObject::StrSigSlotMap& globalStrSigSlotMap = this->globalStrSigSlotMap();
	member_BObject::SlotArray& globalSlots = globalStrSigSlotMap(signal);
	for (int i = 0; i < globalSlots.size(); i++)
	{
		member_BObject::Slot& slot = globalSlots[i];
		if (slot.object == receiver)
			slot(boss, value);
	}
}

